/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package server;

import common.DAO.Factory.DAOFactory;
import common.Objects.Category;
import common.Objects.Component;
import common.Objects.Product;
import server.View.ServerView;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import server.Model.MainModel;
import common.xmlObjects.BaseConnectionXML;
import common.xmlObjects.CategoryXML;
import java.util.Vector;
import common.xmlObjects.ComponentXML;
import common.xmlObjects.ProductXML;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import server.xmlObjects.ServerXML;

/**
 *
 * @author Slasher
 */
public class ClientListener implements Runnable {
    private ServerSocket serverSocket;
    private boolean running;

    public ClientListener() {
        running = false;
    }

    public void run() {
        try {
            while(running) {
                Socket socket = serverSocket.accept();
                Thread t = new Thread(new ConnectionHandler(socket));
                t.start();
            }
        } catch(IOException e) {
            e.printStackTrace();
        }
    }

    public boolean isRunning() {
        return running;
    }

    public void stopServer() {
        try {
            running = false;
            serverSocket.close();
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void startServer() {
        try {
            ServerView.getInstance().addToDisplayArea("Staring Server . . .");
            serverSocket = new ServerSocket(MainModel.getInstance().getPort());
            running = true;
            ServerView.getInstance().addToDisplayArea("Server Awaiting Connections");
        } catch (IOException e) {
            e.printStackTrace();
            ServerView.getInstance().addToDisplayArea("Unable to start, server may already be running in another process");
        }
    }
    private class ConnectionHandler implements Runnable {
        private Socket socket;
        private BufferedReader in;
        private BufferedWriter out;

        public ConnectionHandler() {
        }
        public ConnectionHandler(Socket socket) {
            ServerView.getInstance().addToDisplayArea("connection established");
            this.socket = socket;
            try {
                in = new BufferedReader(new InputStreamReader(
                    socket.getInputStream()));
                out = new BufferedWriter(new OutputStreamWriter(
                    socket.getOutputStream()));
            } catch (IOException e) {e.printStackTrace();}
        }
        public void run() {
            try {
                String lines = in.readLine();

                System.out.println("Read: "+lines);
                InputHandler ih = new InputHandler(lines);
                String xmlString = ih.createResponseXML().toXMLString();
                out.write(xmlString);
                out.flush();
                System.out.println("Responded: "+xmlString);
                this.socket.close();
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private class InputHandler {
        private String input;
        private Document document;

        public InputHandler(String input) {
            this.input = input;
            this.document = BaseConnectionXML.XMLStrTODOMDoc(this.input);
        }
        public ServerXML createResponseXML() {            
            NodeList nodeList = document.getElementsByTagName(BaseConnectionXML.CLIENT);           
            ServerXML serverXML = null;
            if (nodeList.getLength() > 0) {
                Node node = nodeList.item(0);
                Element element = (Element) node;
                
                String action = element.getAttribute(BaseConnectionXML.ACTIONNAME);
                String object = element.getAttribute(BaseConnectionXML.OBJECTNAME);

                ServerView.getInstance().addToDisplayArea("Action: "+action+" Object: "+object);

                serverXML = new ServerXML(action, object);
                
                if (object.equals(BaseConnectionXML.COMPONENT)) {
                    nodeList = document.getElementsByTagName(BaseConnectionXML.COMPONENT);
                    node = nodeList.item(0);                    
                    Component component = new Component();
                    if (node != null) {
                        component = new ComponentXML(node).getObject();
                    }

                    boolean status = true;
                    if (action.equals(BaseConnectionXML.ADD)) {
                        status = DAOFactory.getDAOFactory().getComponentDAO().createComponent(component);
                    }
                    else if (action.equals(BaseConnectionXML.EDIT)) {
                        status = DAOFactory.getDAOFactory().getComponentDAO().editComponent(component);
                    }
                    else if (action.equals(BaseConnectionXML.DELETE)) {
                        status = DAOFactory.getDAOFactory().getComponentDAO().deleteComponent(component.getId());
                    }
                    else if (action.equals(BaseConnectionXML.GET)) {
                        component = DAOFactory.getDAOFactory().getComponentDAO().getComponent(component.getId());
                        if (component == null) {
                            status = false;
                        } else {
                            serverXML.addChildNode(new ComponentXML(component));
                        }
                    }
                    else if (action.equals(BaseConnectionXML.GETALL) || action.equals("getphplist")) {
                        status = false;
                        Vector<Component> components = DAOFactory.getDAOFactory().getComponentDAO().getComponents();
                        for (Component c : components) {
                            if (action.equals("getphplist")) {
                                if (c.getCategoryId() == component.getCategoryId()) {
                                    serverXML.addChildNode(new ComponentXML(String.valueOf(c.getId()),c.getName(),null,null,null,null));
                                    status = true;
                                }
                            } else {
                                serverXML.addChildNode(new ComponentXML(c));
                                status = true;
                            }
                        }                        
                    } else {
                        status = false;
                    }
                    if (status == false) {
                        serverXML.setObjectValue(BaseConnectionXML.FAILED);
                    }
                } else if (object.equals(BaseConnectionXML.PRODUCT)) {                    
                    nodeList = document.getElementsByTagName(BaseConnectionXML.PRODUCT);
                    node = nodeList.item(0);
                    Product product = new Product();
                    if (node != null) {
                        product = new ProductXML(node).getObject();
                    }

                    boolean status = true;
                    if (action.equals(BaseConnectionXML.ADD)) {
                        status = DAOFactory.getDAOFactory().getProductDAO().createProduct(product);
                    }
                    else if (action.equals(BaseConnectionXML.EDIT)) {
                        status = DAOFactory.getDAOFactory().getProductDAO().editProduct(product);
                    }
                    else if (action.equals(BaseConnectionXML.DELETE)) {
                        status = DAOFactory.getDAOFactory().getProductDAO().deleteProduct(product.getId());
                    }
                    else if (action.equals(BaseConnectionXML.GET)) {
                        product = DAOFactory.getDAOFactory().getProductDAO().getProduct(product.getId());
                        if (product == null) {
                            status = false;
                        } else {
                            serverXML.addChildNode(new ProductXML(product));
                        }
                    }
                    else if (action.equals(BaseConnectionXML.GETALL) || action.equals("getphplist")) {
                        status = false;
                        Vector<Product> products = DAOFactory.getDAOFactory().getProductDAO().getProducts();
                        for (Product p : products) {
                            if (action.equals("getphplist")) {
                                serverXML.addChildNode(new ProductXML(String.valueOf(p.getId()), p.getName(), null, null, null));
                                status = true;
                            } else {
                                serverXML.addChildNode(new ProductXML(p));
                                status = true;
                            }
                        }
                    } else {
                        status = false;
                    }
                    if (status == false) {
                        serverXML.setObjectValue(BaseConnectionXML.FAILED);
                    }
                }
                else if (object.equals(BaseConnectionXML.CATEGORY)) {
                    nodeList = document.getElementsByTagName(BaseConnectionXML.CATEGORY);
                    node = nodeList.item(0);
                    Category category = new Category();
                    if (node != null) {
                        category = new CategoryXML(node).getObject();
                    }

                    boolean status = true;
                    if (action.equals(BaseConnectionXML.ADD)) {
                        status = DAOFactory.getDAOFactory().getCategoryDAO().createCategory(category);
                    }
                    else if (action.equals(BaseConnectionXML.DELETE)) {
                        status = DAOFactory.getDAOFactory().getCategoryDAO().deleteCategory(category.getId());
                    }
                    else if (action.equals(BaseConnectionXML.GETALL)) {
                        Vector<Category> categorys = DAOFactory.getDAOFactory().getCategoryDAO().getCategorys();
                        if (categorys.size() == 0) {
                            status = false;
                        } else {
                            for (Category c : categorys) {
                                serverXML.addChildNode(new CategoryXML(c));
                            }
                        }
                    } else {
                        status = false;
                    }
                    if (status == false) {
                        serverXML.setObjectValue(BaseConnectionXML.FAILED);
                    }
                }
                
            }
            else {
                ServerView.getInstance().addToDisplayArea("An unknown XML tag was read");
            }  
            return serverXML;
        }
    }
}